package com.flynn.rock.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.flynn.rock.model.PageResult;
import com.flynn.rock.model.dto.system.UserAccountDto;
import com.flynn.rock.system.convert.AbstractMessageConvert;
import com.flynn.rock.system.entity.SysMessageEntity;
import com.flynn.rock.system.model.request.PageUserMessageRequest;
import com.flynn.rock.system.model.vo.MessageCountVo;
import com.flynn.rock.system.model.vo.MessageVo;
import com.flynn.rock.system.repository.SysMessageRepository;
import com.flynn.rock.system.service.SysMessageService;
import com.flynn.rock.util.PageUtil;
import com.flynn.rock.util.SecurityUtil;
import jakarta.annotation.Resource;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
public class SysMessageServiceImpl implements SysMessageService {

    @Resource
    private SysMessageRepository sysMessageRepository;

    @Override
    public MessageCountVo getUserMessageCount() {
        UserAccountDto currentUser = SecurityUtil.getCurrentUser();
        Long unreadMessageNum = sysMessageRepository.countUnreadMessageNum(currentUser.getUserId());
        return MessageCountVo.builder()
                .unreadMessageCount(unreadMessageNum)
                .build();
    }

    @Transactional
    @Override
    public void readAllUserMessage() {
        Long currentUserId = SecurityUtil.getCurrentUserId();
        sysMessageRepository.readAllUserMessage(currentUserId, LocalDateTime.now());
    }

    @Override
    public PageResult<MessageVo> pageUserMessage(PageUserMessageRequest request) {
        Long currentUserId = SecurityUtil.getCurrentUserId();
        PageRequest pageRequest = PageRequest.of(0, 9999);
        pageRequest = pageRequest.withSort(
                Sort.sort(SysMessageEntity.class)
                        .by(SysMessageEntity::getCreateTime)
                        .descending()
        );
        Page<SysMessageEntity> entityPage = sysMessageRepository.findAll(
                ((root, query, criteriaBuilder) -> {
                    List<Predicate> predicates = new ArrayList<>();
                    predicates.add(criteriaBuilder.equal(root.get("toUserId"), currentUserId));
                    if (StrUtil.isNotBlank(request.getMessageTitle())) {
                        predicates.add(criteriaBuilder.like(root.get("messageTitle"), "%" + request.getMessageTitle() + "%"));
                    }
                    Path<Object> readMessageTime = root.get("readMessageTime");
                    if (PageUserMessageRequest.MessageQueryType.UNREAD.equals(request.getMessageQueryType())) {
                        predicates.add(criteriaBuilder.isNull(readMessageTime));
                    } else if (PageUserMessageRequest.MessageQueryType.READ.equals(request.getMessageQueryType())) {
                        predicates.add(criteriaBuilder.isNotNull(readMessageTime));
                    }
                    return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
                }),
                pageRequest);
        return PageUtil.toPage(entityPage.map(AbstractMessageConvert.INSTANCE::toMessageVo));
    }

    @Override
    public MessageVo getMessageDetail(Long messageId) {
        SysMessageEntity sysMessageEntity = sysMessageRepository.findById(messageId).orElseThrow();
        if (Objects.isNull(sysMessageEntity.getReadMessageTime())) {
            sysMessageEntity.setReadMessageTime(LocalDateTime.now());
            sysMessageRepository.save(sysMessageEntity);
        }
        return AbstractMessageConvert.INSTANCE.toMessageVo(sysMessageEntity);
    }
}
